package com.atguigu.crowd.handler;

import com.atguigu.crowd.api.MySQLRemoteService;
import com.atguigu.crowd.api.RedisRemoteService;
import com.atguigu.crowd.config.OSSProperties;
import com.atguigu.crowd.config.ShortMessageProperties;
import com.atguigu.crowd.constant.CrowdConstant;
import com.atguigu.crowd.entity.po.MemberPO;
import com.atguigu.crowd.entity.vo.*;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import org.omg.PortableInterceptor.INACTIVE;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Controller
public class MemberHandler {


    @Autowired
    private OSSProperties ossProperties;

    @Autowired
    private ShortMessageProperties shortMessageProperties;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;
    @Autowired
    private RedisRemoteService redisRemoteService;


    //用户认证类型
    @RequestMapping("/auth/member/auth2")
    public String memberAuth2(HttpServletRequest request,HttpSession session){
        Integer userType =Integer.parseInt(request.getParameter("userType"));

        session.setAttribute("userType",userType);
        return "member-auth2";
    }

    //用户实名认证第3步
    //收集基本信息页的数据 跳转到资质文件上传页
    @RequestMapping("/auth/member/auth3")
    public String memberAuth3(MemberAuthVO memberAuthVO,
                              // 用来将收集了一部分数据的ProjectVO对象存入Session域
                              HttpSession session,

                              // 用来在当前操作失败后返回上一个表单页面时携带提示消息
                              ModelMap modelMap){


//        System.out.println("memberAuth3--1---memberAuthVO: "+memberAuthVO);
        MemberLoginVO memberLoginVO = (MemberLoginVO) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER);

        Integer memberId = memberLoginVO.getId();

        memberAuthVO.setId(memberId);

        Integer userType = (Integer)session.getAttribute("userType");
        memberAuthVO.setUserType(userType);

//        System.out.println("memberAuth3---memberAuthVO: "+memberAuthVO);
        //放入session
        session.setAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH, memberAuthVO);

        //下个页面继续收集信息
        return "redirect:http://localhost:8888/auth/member/auth4";

    }


    //资质文件上传页   身份证照片和过往文件上传到OSS
    @RequestMapping("/auth/member/auth5")
    public String memberAuth5(

                              // 接收上传的手持身份证照片
                              MultipartFile idCardImgPath,

                              // 接收上传的过往作品
                             MultipartFile passWorksPath,

                              // 用来将收集了一部分数据的ProjectVO对象存入Session域
                              HttpSession session,

                              // 用来在当前操作失败后返回上一个表单页面时携带提示消息
                              ModelMap modelMap) throws IOException {


        MemberAuthVO memberAuthVO = (MemberAuthVO)session.getAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH);
//        System.out.println("memberAuthVO: "+memberAuthVO);

        //放入session
//        session.setAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH, memberAuthVO);
//        System.out.println("idCardImgPath: "+idCardImgPath);
        //判断身份证照片是否上传
        boolean idCardImgPathEmpty = idCardImgPath.isEmpty();

        if(idCardImgPathEmpty){
            //没有手持身份证图片 则返回到表单页面并显示错误消息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_IDCARD_PIC_EMPTY);
            return "member-auth4";
        }


        //不是空的 上传
        ResultEntity<String> uploadIdCardPicResultEntity = CrowdUtil.uploadFileToOss(
                ossProperties.getEndPoint(),
                ossProperties.getAccessKeyId(),
                ossProperties.getAccessKeySecret(),
                idCardImgPath.getInputStream(),
                ossProperties.getBucketName(),
                ossProperties.getBucketDomain(),
                idCardImgPath.getOriginalFilename());

        //对于过往作品集同理
        boolean passWorksPathEmpty = passWorksPath.isEmpty();

        if(passWorksPathEmpty){
            //没有手过往作品集 则返回到表单页面并显示错误消息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_PASS_WORKS_EMPTY);
            return "member-auth4";
        }
        //不是空的 上传
        ResultEntity<String> uploadPassWorksResult = CrowdUtil.uploadFileToOss(
                ossProperties.getEndPoint(),
                ossProperties.getAccessKeyId(),
                ossProperties.getAccessKeySecret(),
                passWorksPath.getInputStream(),
                ossProperties.getBucketName(),
                ossProperties.getBucketDomain(),
                passWorksPath.getOriginalFilename());

        //判断头图是否上传成功
        if(ResultEntity.SUCCESS.equals(uploadIdCardPicResultEntity.getResult())){
            //成功 则从返回的数据中获取图片访问路径
            String idCardPicResultEntityData = uploadIdCardPicResultEntity.getData();

            // 6.存入ProjectVO对象中
            memberAuthVO.setIdCardImgPath(idCardPicResultEntityData);
        }else {
            // 7.如果上传失败则返回到表单页面并显示错误消息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, "手持身份证照片上传失败");
            return "member-auth4";
        }


        if(ResultEntity.SUCCESS.equals(uploadPassWorksResult.getResult())){
            //成功 则从返回的数据中获取图片访问路径
            String passWorksResultData = uploadPassWorksResult.getData();

            // 6.存入ProjectVO对象中
            memberAuthVO.setPassWorksPath(passWorksResultData);
        }else {
            // 7.如果上传失败则返回到表单页面并显示错误消息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, "过往作品集上传失败");
            return "member-auth4";
        }
        session.setAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH, memberAuthVO);

        //下个页面继续收集信息
        return "redirect:http://localhost:8888/auth/member/auth6";

    }

//    //手机确认页
    @RequestMapping("/auth/member/auth7")
    public String  memberAuth7(String phoneNum,HttpSession session){
        //取出MemberAuthVO
        MemberAuthVO memberAuthVO = (MemberAuthVO)session.getAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH);

        memberAuthVO.setPhoneNum(phoneNum);
//        System.out.println("memberAuth7---memberAuthVO:"+ memberAuthVO);
        //修改MemberAuthVO
        session.setAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH, memberAuthVO);

        return "redirect:http://localhost:8888/auth/member/auth8";
    }



    //申请确认页
    @RequestMapping("/auth/member/auth9")
    public String  memberAuth9(Integer phoneCode,ModelMap modelMap,HttpSession session){

        MemberAuthVO memberAuthVO = (MemberAuthVO)session.getAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH);
//        System.out.println("memberAuth9---memberAuthVO"+memberAuthVO);

        //验证验证码
        //2.拼接手机号与常量形成key 在redis中获取对应value
        String key = CrowdConstant.REDIS_CODE_PREFIX+memberAuthVO.getPhoneNum();
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);

        //3.检查redis查询操作是否成功/有效 需要SUCCESS且value不是Null
        if(ResultEntity.FAILED.equals(resultEntity.getResult())){
            //失败 回到注册页 并显示错误消息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,resultEntity.getMessage());
            return "member-auth5";
        }
        String redisCode = resultEntity.getData();
        if(redisCode == null){
            //验证码为null
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXISTS);
            return "member-auth5";
        }
        //4.比对填入的验证码是否一致
        if(!(phoneCode.equals(redisCode))){
            //不一致 返回注册页 并显示错误消息 验证码不正确
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_INVALID);
        }

        //一致 删除redis中验证码 并将密码加密
        redisRemoteService.removeRedisKeyRemote(key);

        //保存信息
        ResultEntity<String> stringResultEntity = mySQLRemoteService.saveMemberAuthVORemote(memberAuthVO);

        // 6.判断远程的保存操作是否成功
        String result = stringResultEntity.getResult();
        if(ResultEntity.FAILED.equals(result)) {

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, stringResultEntity.getMessage());

            return "member-auth5";
        }

        // 7.将临时的ProjectVO对象从Session域移除
        session.removeAttribute(CrowdConstant.ATTR_NAME_TEMPLE_MEMBER_AUTH);


        return "redirect:http://localhost:8888/auth/member/my/crowd";
    }



    //用户申请延期页面
    @RequestMapping("/auth/member/projectInfo")
    public String memberProjectInfo(
          HttpServletRequest request,
             ModelMap modelMap){
            modelMap.addAttribute("projectId",request.getParameter("projectId"));
        modelMap.addAttribute("status",request.getParameter("status"));
        modelMap.addAttribute("delayDay",request.getParameter("delayDay"));
        modelMap.addAttribute("delayNumber",request.getParameter("delayNumber"));
        return "member-projectInfo";
    }


    //用户申请延期
    @RequestMapping(value = "/auth/member/applyForDelay")
    public String applyForDelay(
            HttpServletRequest request,
            Integer delayDayNow,
            ModelMap modelMap,
            HttpSession session

    ){
//        System.out.println("delayDayNow:"+delayDayNow);
        Integer projectId = Integer.parseInt(request.getParameter("projectId"));
//        System.out.println("projectId: "+projectId);
        Integer status = Integer.parseInt(request.getParameter("status"));
//        System.out.println("status: "+status);
        Integer delayDay = Integer.parseInt(request.getParameter("delayDay"));
//        System.out.println("delayDay: "+delayDay);
        Integer delayNumber = Integer.parseInt(request.getParameter("delayNumber"));
//        System.out.println("delayNumber: "+delayNumber);


        //如果还没有到开发阶段 不能申请延期


        String message="111";
        //不能延期
        if(delayNumber >= 3|| (delayDay+delayDayNow)>=100||(status<1&&status>4)){
            message = "申请失败";
        }else {
            //可以延期 数据库操作 修改字段即可 修改 delayDay delayNumber developmentDay

            delayDay = delayDayNow+delayDay;
            delayNumber++;
            ResultEntity<String> resultEntity = mySQLRemoteService.updateMemberApplyRemote(projectId, delayDay, delayNumber);
            if(ResultEntity.FAILED.equals(resultEntity.getResult())){
                //更新失败  在页面显示
             //   modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,resultEntity.getMessage());
               message = "申请失败";
            }else {
                message = "申请通过";
            }
        }

//        System.out.println(message);

        session.setAttribute("message",message);

       return "redirect:http://localhost:8888/auth/member/apply/result";

    }

    //用户发起的所有项目 用户member-crowd页面填充
    @RequestMapping("/auth/member/my/crowd")
    public String showCrowdPage(ModelMap modelMap,HttpSession session){
        MemberLoginVO memberLoginVO = (MemberLoginVO) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER);

        Integer memberId = memberLoginVO.getId();
        ResultEntity<List<DetailProjectVO>> memberCrowdProjectRemote = mySQLRemoteService.getMemberCrowdProjectRemote(memberId);
//        System.out.println("memberCrowdProjectRemote:"+memberCrowdProjectRemote);
        List<DetailProjectVO> projectVOS = memberCrowdProjectRemote.getData();
//        System.out.println("projectVOS:"+projectVOS);
        if(ResultEntity.FAILED.equals(memberCrowdProjectRemote.getResult())){
            //查询失败 在crowd显示错误信息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,memberCrowdProjectRemote.getMessage());
            return "member-crowd";
        }
        modelMap.addAttribute("memberProjectCrowd",projectVOS);
        return "member-crowd";
    }



    //退出登录 回到首页
    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session){
        session.invalidate();
        return "redirect:/";
    }

    //登录操作
    @RequestMapping("/auth/member/do/login")
    public String login(
            @RequestParam("loginacct") String loginacct,
            @RequestParam("userpswd") String userpswd,
            ModelMap modelMap,
            HttpSession session
    ){

        //根据账号进行查询
        ResultEntity<MemberPO> resultEntity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);
        MemberPO memberPo =resultEntity.getData();
//        System.out.println("登录的memberPo.getFailednum(): "+memberPo.getFailedNum());
        if(ResultEntity.FAILED.equals(resultEntity.getResult())){
            //查询失败 在登录页显示错误信息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,resultEntity.getMessage());
            return "member-login";
        }
        //查询成功 看查询是否查询出memberPO
        if(memberPo == null){
            //为空 则在登录页显示错误信息 密码/账号错误
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_LOGIN_FAILED);
        }

        //memberPO有值 比较密码是否一致
        String userpswdDataBase = memberPo.getUserpswd();

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        boolean matcheResult = passwordEncoder.matches(userpswd, userpswdDataBase);

        //不一致
        if(!matcheResult) {
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);

            return "member-login";
        }

        //一致 将MemberPO对象转换为MemberLoginVO对象存入session域 以便登录成功后显示
        MemberLoginVO memberLoginVO = new MemberLoginVO();
        memberLoginVO.setFailedNum(memberPo.getFailedNum());

        System.out.println("设置登录用户的失败次数");
//        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());
        switch (memberPo.getAuthstatus()){
            case 0:
                memberLoginVO.setAuthstatus(0);
                memberLoginVO.setAuthStatusText("未实名认证");
                break;
            case 1:
                memberLoginVO.setAuthstatus(1);
                memberLoginVO.setAuthStatusText("实名认证审核中");
                break;
            case 2:
                memberLoginVO.setAuthstatus(2);
                memberLoginVO.setAuthStatusText("已实名认证");
                break;
            case 3:
                memberLoginVO.setAuthstatus(3);
                memberLoginVO.setAuthStatusText("实名认证失败");
            default:
                break;
        }
        BeanUtils.copyProperties(memberPo, memberLoginVO);
//        System.out.println("用户状态:"+memberLoginVO.getAuthstatus());

        session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER,memberLoginVO);


        //重定向到会员中心页
//        return "redirect:/auth/member/to/center/page"; //localhost:4000的
        return "redirect:http://localhost:8888/auth/member/to/center/page"; //通过zuul访问
    }

    //完成注册操作 注册成功跳转到登录页面
    @RequestMapping("/auth/do/member/register")
    public String register(MemberVO memberVO, ModelMap modelMap) {
        //1.获取输入的手机号
        String phoneNum = memberVO.getPhoneNum();

        //2.拼接手机号与常量形成key 在redis中获取对应value
        String key = CrowdConstant.REDIS_CODE_PREFIX+phoneNum;
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);

        //3.检查redis查询操作是否成功/有效 需要SUCCESS且value不是Null
        if(ResultEntity.FAILED.equals(resultEntity.getResult())){
            //失败 回到注册页 并显示错误消息
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,resultEntity.getMessage());
            return "member-reg";
        }
        String redisCode = resultEntity.getData();
        if(redisCode == null){
            //验证码为null
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXISTS);
            return "member-reg";
        }
        //4.比对填入的验证码是否一致
//        System.out.println("输入的验证码: "+memberVO.getCode()+" redis生成的验证码："+redisCode);
        if(!(memberVO.getCode().equals(redisCode))){
            //不一致 返回注册页 并显示错误消息 验证码不正确
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_INVALID);
            return "member-reg";
        }

        //一致 删除redis中验证码 并将密码加密
        redisRemoteService.removeRedisKeyRemote(key);

        BCryptPasswordEncoder encoder= new BCryptPasswordEncoder();

        String userpswdBeforeEncode = memberVO.getUserpswd();

        String userpswdAfterEncode = encoder.encode(userpswdBeforeEncode);

        memberVO.setUserpswd(userpswdAfterEncode);

        //执行保存
        // ①创建空的MemberPO对象
        MemberPO memberPO = new MemberPO();

        // ②复制属性
        BeanUtils.copyProperties(memberVO, memberPO);

        // ③调用远程方法
        ResultEntity<String> saveMemberResultEntity = mySQLRemoteService.saveMember(memberPO);

        if(ResultEntity.FAILED.equals(saveMemberResultEntity.getResult())) {

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, saveMemberResultEntity.getMessage());

            return "member-reg";
        }

        // 使用重定向避免刷新浏览器导致重新执行注册流程
        return "redirect:/auth/member/to/login/page";
    }



    //发送短信验证码
    @ResponseBody  //返回的是JSON格式 一定要有ResponseBody 不然会TemplateInputException: Error resolving template [auth/member/send/short/message
    @RequestMapping("/auth/member/send/short/message.json")
    public ResultEntity<String> sendMessage(@RequestParam("phone") String phone){
//        System.out.println("phone "+phone);

        //String host, String path, String phone, String appcode, String sign, String skin) {
        //1.发送验证码到phone手机 传入的参数可以放在配置文件中
        ResultEntity<String> sendMessageResultEntity = CrowdUtil.sendCodeByShortMessage(
                shortMessageProperties.getHost(),
                shortMessageProperties.getPath(),
                phone,
                shortMessageProperties.getAppCode(),
                shortMessageProperties.getTemplateId()
        );

     //   System.out.println(sendMessageResultEntity.getResult());
        //2.判断短信发送结果
        if (ResultEntity.SUCCESS.equals(sendMessageResultEntity.getResult())){
            //3.发送成功 验证码存入Redis
            // ①从上一步操作的结果中获取随机生成的验证码
            String code=sendMessageResultEntity.getData();
//            System.out.println("随机生成的验证码："+code);

            // ②拼接一个用于在Redis中存储数据的key
            String key = CrowdConstant.REDIS_CODE_PREFIX + phone;

         //   System.out.println("key: "+key);
            // ③调用远程接口存入Redis
            ResultEntity<String> saveCodeResultEntity = redisRemoteService.setRedisKeyValueRemoteWithTimeout(key, code, 15, TimeUnit.MINUTES);
         //   System.out.println(saveCodeResultEntity.getResult());
            // ④判断结果
            if(ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())) {

                return ResultEntity.successWithoutData();
            }else {
                return saveCodeResultEntity;
            }
        } else {
            return sendMessageResultEntity;
        }
    }
}
